#include "platform/openal/openal_audio_source.hpp"
#include "AL/al.h"
#include "glm/gtc/type_ptr.hpp"

namespace Xen {

OpenALAudioSource::OpenALAudioSource() {
    ALCall(alGenSources(1, &source_));
    ALCall(alSourcef(source_, AL_PITCH, 1));
    SetVolume(1);
    SetPosition(glm::vec3(0, 0, 0));
    SetVelocity(glm::vec3(0, 0, 0));
}

OpenALAudioSource::~OpenALAudioSource() {
    ALCall(alDeleteSources(1, &source_));
}

void OpenALAudioSource::SetPosition(const glm::vec3& pos) {
    ALCall(alSourcefv(source_, AL_POSITION, glm::value_ptr(pos)));
}

glm::vec3 OpenALAudioSource::GetPosition() const {
    float pos[3];
    ALCall(alGetSourcefv(source_, AL_POSITION, pos));
    return glm::vec3(pos[0], pos[1], pos[2]);
}

void OpenALAudioSource::SetVolume(float volume) {
    ALCall(alSourcef(source_, AL_GAIN, volume));
}

float OpenALAudioSource::GetVolume() const {
    float vol;
    ALCall(alGetSourcef(source_, AL_GAIN, &vol));
    return vol;
}

void OpenALAudioSource::SetVelocity(const glm::vec3& vel) {
    ALCall(alSourcefv(source_, AL_VELOCITY, glm::value_ptr(vel)));
}

glm::vec3 OpenALAudioSource::GetVelocity() const {
    float vel[3];
    ALCall(alGetSourcefv(source_, AL_VELOCITY, vel));
    return glm::vec3(vel[0], vel[1], vel[2]);
}

void OpenALAudioSource::Bind(const Ref<AudioBuffer>& buffer) {
    buffer_ = buffer;
    const OpenALAudioBuffer* openal_buffer = dynamic_cast<OpenALAudioBuffer*>(buffer.get());
    ALCall(alSourcei(source_, AL_BUFFER, openal_buffer->GetBuffer()));
}

Ref<AudioBuffer> OpenALAudioSource::GetBindedBuffer() const {
    return buffer_;
}

void OpenALAudioSource::Unbind() {
    ALCall(alSourcei(source_, AL_BUFFER, 0));
}

void OpenALAudioSource::EnableLoop() {
    ALCall(alSourcei(source_, AL_LOOPING, AL_TRUE));
}

void OpenALAudioSource::DisableLoop() {
    ALCall(alSourcei(source_, AL_LOOPING, AL_FALSE));

}

bool OpenALAudioSource::IsLoop() const {
    int b;
    ALCall(alGetSourcei(source_, AL_LOOPING, &b));
    return b;
}

}
